/*
 * Copyright 2010 Michael Nitsche
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package de.mnit.basis.daten.struktur.container;

import de.mnit.basis.daten.struktur.gruppe.Gruppe2;
import de.mnit.basis.daten.typ.zeit.S_Datum;
import de.mnit.basis.daten.typ.zeit.S_Zeitpunkt;
import de.mnit.basis.fehler.Fehler;


/** @author Michael Nitsche
 * 02.03.2009 Erstellt
 * 20.08.2009 Update-Variable eingeführt
 *
 *
 * Normal wird mit den neu-Funktionen eine Kiste erstellt.
 * Wenn bei einer DB später Spalten hinzu kommen, werden die update-Funktionen verwendet!!!
 */
public final class DBKiste<T> implements S_Kiste<T> {

	public final Class<T> typ;
	public final Integer groesse;
	public final boolean primarykey;
	public final boolean notnull;
	public final boolean autozaehler;
	public final T standard;
	private final A_DBKistenstapel behaelter;
	private final boolean update;
	private String name=null;
	private boolean leer=true;
	private T wert=null;


	private DBKiste(A_DBKistenstapel behaelter, Class<T> typ, T standard, Integer groesse, boolean notnull, boolean primarykey, boolean autozaehler, boolean update) {
		this.behaelter=behaelter;
		this.typ=typ;
		this.groesse=groesse;
		this.notnull=notnull;
		this.primarykey=primarykey;
		this.autozaehler=autozaehler;
		this.standard=standard;
		this.update=update;
	}


	public static <T1> DBKiste<T1> neu(A_DBKistenstapel behaelter, Class<T1> typ, Integer groesse, boolean notnull) {
		return new DBKiste<T1>(behaelter, typ, (T1)null, groesse, notnull, false, false, false);
	}

	public static <T> DBKiste<T> neu(A_DBKistenstapel behaelter, Class<T> typ, Integer groesse, boolean notnull, T init) {
		DBKiste<T> erg=new DBKiste<T>(behaelter, typ, init, groesse, notnull, false, false, false);
		erg.s(init);
		return erg;
	}


	public static DBKiste<Integer> neuPrimaerSchluessel(A_DBKistenstapel behaelter, boolean autozaehler) {
		return new DBKiste<Integer>(behaelter, Integer.class, null, null, true, true, autozaehler, false);
	}

	public static DBKiste<Long> neuPrimaerSchluesselLong(A_DBKistenstapel behaelter, boolean autozaehler) {
		return new DBKiste<Long>(behaelter, Long.class, null, null, true, true, autozaehler, false);
	}

	public static DBKiste<Integer> neuInteger(A_DBKistenstapel behaelter, boolean notnull) {
		return new DBKiste<Integer>(behaelter, Integer.class, null, null, notnull, false, false, false);
	}

	public static DBKiste<Integer> neuInteger(A_DBKistenstapel behaelter, boolean notnull, int standard) {
		return new DBKiste<Integer>(behaelter, Integer.class, standard, null, notnull, false, false, false);
	}

	public static DBKiste<Long> neuLong(A_DBKistenstapel behaelter, boolean notnull) {
		return new DBKiste<Long>(behaelter, Long.class, null, null, notnull, false, false, false);
	}

	public static DBKiste<Long> neuLong(A_DBKistenstapel behaelter, boolean notnull, long standard) {
		return new DBKiste<Long>(behaelter, Long.class, standard, null, notnull, false, false, false);
	}

	public static DBKiste<String> neuString(A_DBKistenstapel behaelter, int groesse, boolean notnull) {
		return new DBKiste<String>(behaelter, String.class, null, groesse, notnull, false, false, false);
	}

	public static DBKiste<String> neuString(A_DBKistenstapel behaelter, int groesse, boolean notnull, String standard) {
		return new DBKiste<String>(behaelter, String.class, standard, groesse, notnull, false, false, false);
	}

	public static DBKiste<String> neuStringFlex(A_DBKistenstapel behaelter, boolean notnull) {
		return new DBKiste<String>(behaelter, String.class, null, null, notnull, false, false, false);
	}

	public static DBKiste<S_Datum> neuDatum(A_DBKistenstapel behaelter, boolean notnull) {
		return new DBKiste<S_Datum>(behaelter, S_Datum.class, null, null, notnull, false, false, false);
	}

	public static DBKiste<S_Zeitpunkt> neuZeitpunkt(A_DBKistenstapel behaelter, boolean notnull) {
		return new DBKiste<S_Zeitpunkt>(behaelter, S_Zeitpunkt.class, null, null, notnull, false, false, false);
	}

	public static DBKiste<Boolean> neuBool(A_DBKistenstapel behaelter, boolean notnull) {
		return new DBKiste<Boolean>(behaelter, Boolean.class, null, null, notnull, false, false, false);
	}

	public static DBKiste<Boolean> neuBool(A_DBKistenstapel behaelter, boolean notnull, boolean standard) {
		return new DBKiste<Boolean>(behaelter, Boolean.class, standard, null, notnull, false, false, false);
	}

	// UPDATES

	public static <T1> DBKiste<T1> update(A_DBKistenstapel behaelter, Class<T1> typ, Integer groesse, boolean notnull) {
		return new DBKiste<T1>(behaelter, typ, (T1)null, groesse, notnull, false, false, true);
	}

	public static <T> DBKiste<T> update(A_DBKistenstapel behaelter, Class<T> typ, Integer groesse, boolean notnull, T init) {
		DBKiste<T> erg=new DBKiste<T>(behaelter, typ, init, groesse, notnull, false, false, true);
		erg.s(init);
		return erg;
	}


	public static DBKiste<Integer> updatePrimaerSchluessel(A_DBKistenstapel behaelter, boolean autozaehler) {
		return new DBKiste<Integer>(behaelter, Integer.class, null, null, true, true, autozaehler, true);
	}

	public static DBKiste<Integer> updateInteger(A_DBKistenstapel behaelter, boolean notnull) {
		return new DBKiste<Integer>(behaelter, Integer.class, null, null, notnull, false, false, true);
	}

	public static DBKiste<Integer> updateInteger(A_DBKistenstapel behaelter, boolean notnull, Integer standard) {
		return new DBKiste<Integer>(behaelter, Integer.class, standard, null, notnull, false, false, true);
	}

	public static DBKiste<String> updateString(A_DBKistenstapel behaelter, int groesse, boolean notnull) {
		return new DBKiste<String>(behaelter, String.class, null, groesse, notnull, false, false, true);
	}

	public static DBKiste<String> updateStringFlex(A_DBKistenstapel behaelter, boolean notnull) {
		return new DBKiste<String>(behaelter, String.class, null, null, notnull, false, false, true);
	}

	public static DBKiste<S_Datum> updateDatum(A_DBKistenstapel behaelter, boolean notnull) {
		return new DBKiste<S_Datum>(behaelter, S_Datum.class, null, null, notnull, false, false, true);
	}

	public static DBKiste<S_Zeitpunkt> updateZeitpunkt(A_DBKistenstapel behaelter, boolean notnull) {
		return new DBKiste<S_Zeitpunkt>(behaelter, S_Zeitpunkt.class, null, null, notnull, false, false, true);
	}

	public static DBKiste<Boolean> updateBool(A_DBKistenstapel behaelter, boolean notnull) {
		return new DBKiste<Boolean>(behaelter, Boolean.class, null, null, notnull, false, false, true);
	}

	public static DBKiste<Boolean> updateBool(A_DBKistenstapel behaelter, boolean notnull, boolean standard) {
		return new DBKiste<Boolean>(behaelter, Boolean.class, standard, null, notnull, false, false, true);
	}

	// FUNKTIONEN

	public void s(T wert) {
		if(this.notnull && wert==null)
			Fehler.sonstige.da_Verboten("Ein Pflichtfeld darf nicht NULL sein!", this.gName());
		this.wert=wert;
		this.leer=false;
	}

	public T		g()				{ return this.wert; }
	public boolean 	gLeer() 		{ return this.leer; }
	public boolean 	gNichtNull()   	{ return this.notnull; }
	public boolean 	gPflicht() 		{ return this.notnull; }
	public Class<T> gTyp()   		{ return this.typ; }
	public Integer 	gGroesse()   	{ return this.groesse; }
	public boolean 	gPrimaryKey()	{ return this.primarykey; }
	public boolean 	gAutozaehler()	{ return this.autozaehler; }
	public T	 	gStandard() 	{ return this.standard; }
	public boolean 	gUpdate()	 	{ return this.update; }
//	public A_DBKistenstapel gBehaelter()	{ return this.behaelter; }

	public String gName() {
		return this.name!=null ? this.name : (this.name=behaelter.gKisten().gSchluessel(this).toLowerCase());
	}

	public boolean gGueltig() {
		return this.gFehler() == null;
	}

	public String gFehler() {
		if(!this.primarykey && this.notnull && this.wert==null) //Bei neuer Eingabe ist ID z.B. immer Null!
			return "Pflichtfeld ist NULL";
		if(this.typ == String.class && (""+this.wert).length() > this.groesse)
			return "Text ist zu lang";

		return null;
	}

	public String toString() { //Evtl. ohne Kiste()
		return this.getClass().getSimpleName()+"("+this.g()+")";
	}

	public DBKiste<T> kopie() {
		DBKiste<T> kopie=new DBKiste<T>(this.behaelter, this.typ, this.standard, this.groesse, this.notnull, this.primarykey, this.autozaehler, this.update);
		kopie.name=this.name;
		kopie.leer=this.leer;
		kopie.wert=this.wert;
		return kopie;
	}


	public void sKopie(Gruppe2<Boolean,T> g) {
		this.leer=g.g1();
		this.wert=g.g2();
	}

	public Gruppe2<Boolean,T> gKopie() {
		return Gruppe2.neu(this.leer, this.wert);
	}
}
